home *** CD-ROM | disk | FTP | other *** search
-
- /*************************************************************************/
- /* Play.c */
- /*Contains code used to play samples (mono out of one or both speakers, */
- /*and stereo). */
- /*************************************************************************/
-
- #include <exec/types.h>
- #include <exec/exec.h>
- #include <devices/audio.h>
- #include <dos/dos.h>
- #include <intuition/intuition.h>
- #include <intuition/intuitionbase.h>
- #include <graphics/gfxbase.h>
- #include <stdlib.h>
-
- #include "dsound.h"
-
- #include <proto/intuition.h>
- #include <proto/exec.h>
- #include <proto/dos.h>
-
- UBYTE rightAMap[]={4,2,1,8};
- UBYTE leftAMap[]={1,8,2,4};
- UBYTE eitherAMap[]={1,2,4,8};
- UBYTE bothAMap[]={8,3,5,10};
-
- extern UBYTE volume;
- extern UWORD speed;
- extern ULONG bufSize;
-
- extern BOOL readAll;
- extern BOOL loop;
- extern struct Window *window;
-
- /*Play a sample out of one speaker (left, right, or either)*/
- void playMonoSample(BPTR file,channel audioChannel,struct Voice8Header *vhdr,
- ULONG len)
- {
- struct IOAudio *iob1,*iob2;
- ULONG toRead;
- ULONG sampleSize=len;
- BOOL done=FALSE;
- UBYTE *allocationMap;
-
- /*Load the entire sample into memory, if the user so specified*/
- if(readAll)
- {
- storeLeft(file,len,bufSize);
- file=0L;
- }
-
- /*Decide which audio channel will be allocated*/
- switch(audioChannel)
- {
- case MONO_LEFT:
- allocationMap=leftAMap;
- break;
- case MONO_RIGHT:
- allocationMap=rightAMap;
- break;
- case UNSPECIFIED:
- allocationMap=eitherAMap;
- break;
- }
-
- /*Get the first audio channel*/
- iob1=GetAudioChannel(bufSize,allocationMap);
- if(iob1==NULL)
- {
- WriteMsg("Couldn't create the first buffer\n");
- cleanup(150);
- }
-
- /* If the user didn't specify a volume, get it from the VHDR */
- if(volume==0)
- volume=(vhdr->volume>>10);
-
- /* If the VHDR gave a volume of zero, use maximum volume*/
- if(volume==0)
- volume=64;
-
- /* Get the samples/sec rate (either the rate given by the user, or the*/
- /* rate found in the VHDR) */
- if(speed==0)
- speed=1000000000/(vhdr->samplesPerSec*279);
- else
- speed=1000000000/(speed*279);
-
- InitAudioChannel(iob1,volume,speed);
-
- /*Get the 2nd audio channel*/
- iob2=DuplicateAudioChannel(iob1);
-
- if(iob2==NULL)
- {
- FreeAudioChannel(iob1);
- WriteMsg("Couldn't create the second buffer\n");
- cleanup(175);
- }
-
- /* Load the first buffer*/
- toRead=MIN(len,bufSize);
- LoadAudioBuffer(file,iob1,toRead);
-
- len-=toRead;
- if(len==0 && loop)
- {
- len=sampleSize;
- Seek(file,-sampleSize,OFFSET_CURRENT);
- }
-
- /*Store the number of samples to be played*/
- iob1->ioa_Length=toRead;
-
- /* Make sure there's enough data so that we have something to put in */
- /* the second buffer */
- if(len!=0)
- {
- toRead=MIN(len,bufSize);
- LoadAudioBuffer(file,iob2,toRead);
- len-=toRead;
- if(len==0 && loop)
- {
- len=sampleSize;
- Seek(file,-sampleSize,OFFSET_CURRENT);
- }
- iob2->ioa_Length=toRead;
- }
- else
- /* It appears that the entire sound sample is small enough to */
- /* fit into the first buffer, so don't play the second */
- iob2->ioa_Length=0;
-
- /*And queue up the play requests*/
- BeginIO((struct IORequest *)iob1);
- if(iob2->ioa_Length!=0)
- BeginIO((struct IORequest *)iob2);
-
- /* If the sound sample was small enough to fit into the two buffers, */
- /* play them then finish up */
- if(len==0)
- {
- Wait((1<<iob1->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) +
- (1<<window->UserPort->mp_SigBit));
-
- /* vvvv Bug fix */
- if(iob2->ioa_Length!=0 && GetMsg(window->UserPort)==NULL)
- Wait((1<<iob2->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
- (1<<window->UserPort->mp_SigBit));
-
- done=TRUE;
- }
-
- /*Otherwise, play those samples then read more from disk*/
-
- /*Loop while there's stuff to read*/
- while(!done)
- {
- /*Fill the first buffer*/
- Wait((1<<iob1->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
- (1<<window->UserPort->mp_SigBit));
-
- toRead=MIN(len,bufSize);
-
- if(GetMsg(window->UserPort)!=NULL)
- {
- done=TRUE;
- break;
- }
- else
- if(toRead==0)
- {
- /*If there's no stuff left to read, wait 'till the second buffer*/
- /*finishes, then quit*/
- Wait((1<<iob2->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
- (1<<window->UserPort->mp_SigBit));
- done=TRUE;
- break;
- }
-
- LoadAudioBuffer(file,iob1,toRead);
- len-=toRead;
- if(len==0 && loop)
- {
- len=sampleSize;
- Seek(file,-sampleSize,OFFSET_CURRENT);
- }
-
- iob1->ioa_Length=toRead;
-
- /*Play the first buffer*/
- BeginIO((struct IORequest *)iob1);
-
- /*Wait for the second buffer to finish*/
- Wait((1<<iob2->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
- (1<<window->UserPort->mp_SigBit));
-
- toRead=MIN(len,bufSize);
-
- if(GetMsg(window->UserPort)!=NULL)
- {
- done=TRUE;
- break;
- }
- else
- if(toRead==0)
- {
- /*If there's no stuff left to read, wait 'till the first buffer*/
- /*finishes, then quit*/
- Wait((1<<iob1->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
- (1<<window->UserPort->mp_SigBit));
- done=TRUE;
- break;
- }
-
- /*Reload it*/
- LoadAudioBuffer(file,iob2,toRead);
- len-=toRead;
- if(len==0 && loop)
- {
- len=sampleSize;
- Seek(file,-sampleSize,OFFSET_CURRENT);
- }
- iob2->ioa_Length=toRead;
-
- /*Play it*/
- BeginIO((struct IORequest *)iob2);
- }
-
- /*Restore the buffer lengths, so that FreeAudio() channel, etc., knows*/
- /*how much memory to free*/
- iob1->ioa_Length=iob2->ioa_Length=bufSize;
-
- FreeAudioChannel(iob1);
- DeleteDuplication(iob2);
-
- return;
- }
-
- /*Play a stereo sample out of both speakers*/
- /*If the user specifies that just one of the two stereo channels will*/
- /*be played, DSound.c calls playMonoSample*/
-
- void playStereoSample(BPTR leftFile,channel audioChannel,
- struct Voice8Header *vhdr, ULONG length, char *filename)
- {
- struct IOAudio *iob1_right,*iob2_right,*iob1_left,*iob2_left;
- ULONG toRead;
- ULONG sampleSize=length;
- BOOL done=FALSE;
- BPTR rightFile;
-
- /*Open the file again*/
- rightFile=dupFileHandle(leftFile,filename);
-
- /*And position ourselves at the start of the right channel's data*/
- Seek(rightFile,length,OFFSET_CURRENT);
-
- /*Read the entire sample into memory, if specified*/
- if(readAll)
- {
- storeLeft(leftFile,length,bufSize);
- storeRight(rightFile,length,bufSize);
- Close(rightFile);
- leftFile=0L;
- rightFile=4L;
- }
-
- /*Get the first audio channel*/
- iob1_left=GetAudioChannel(bufSize,leftAMap);
- if(iob1_left==NULL)
- {
- WriteMsg("Couldn't create the first stereo buffer\n");
- cleanup(150);
- }
-
- iob1_right=GetAudioChannel(bufSize,rightAMap);
- if(iob1_right==NULL)
- {
- WriteMsg("Couldn't create the second stereo buffer\n");
- cleanup(150);
- }
-
- /* If the user didn't specify a volume, get it from the VHDR */
- if(volume==0)
- volume=(vhdr->volume>>10);
-
- /* If the VHDR gave a volume of zero, use maximum volume*/
- if(volume==0)
- volume=64;
-
- /* Get the samples/sec rate (either the rate given by the user, or the*/
- /* rate found in the VHDR) */
- if(speed==0)
- speed=1000000000/(vhdr->samplesPerSec*279);
- else
- speed=1000000000/(speed*279);
-
- InitAudioChannel(iob1_left,volume,speed);
- InitAudioChannel(iob1_right,volume,speed);
-
- /*Get the 2nd audio channel*/
- iob2_left=DuplicateAudioChannel(iob1_left);
-
- if(iob2_left==NULL)
- {
- FreeAudioChannel(iob1_left);
- FreeAudioChannel(iob1_right);
- WriteMsg("Couldn't create the second buffer");
- cleanup(175);
- }
-
- iob2_right=DuplicateAudioChannel(iob1_right);
- if(iob2_right==NULL)
- {
- FreeAudioChannel(iob1_left);
- DeleteDuplication(iob2_left);
- FreeAudioChannel(iob1_right);
- WriteMsg("Couldn't create the second buffer");
- cleanup(175);
- }
-
-
- /* Load the first buffer*/
- toRead=MIN(length,bufSize);
- LoadAudioBuffer(leftFile,iob1_left,toRead);
- LoadAudioBuffer(rightFile,iob1_right,toRead);
- iob1_left->ioa_Length=iob1_right->ioa_Length=toRead;
- iob1_right->ioa_Length=iob1_left->ioa_Length=toRead;
-
- length-=toRead;
- if(length==0 && loop)
- {
- length=sampleSize;
- Seek(leftFile,-sampleSize,OFFSET_CURRENT);
- Seek(rightFile,-sampleSize,OFFSET_CURRENT);
- }
-
- /* Make sure there's enough data so that we have something to put in */
- /* the second buffer */
- if(length!=0)
- {
- toRead=MIN(length,bufSize);
- LoadAudioBuffer(leftFile,iob2_left,toRead);
- LoadAudioBuffer(rightFile,iob2_right,toRead);
- length-=toRead;
- if(length==0 && loop)
- {
- length=sampleSize;
- Seek(leftFile,-sampleSize,OFFSET_CURRENT);
- Seek(rightFile,-sampleSize,OFFSET_CURRENT);
- }
-
- iob2_right->ioa_Length=iob2_left->ioa_Length=toRead;
- }
- else
- /* It appears that the entire sound sample is small enough to */
- /* fit into the first buffer, so don't play the second */
- iob2_left->ioa_Length=iob2_right->ioa_Length=0;
-
- /*And queue up the play requests*/
- BeginIO((struct IORequest *)iob1_left);
- BeginIO((struct IORequest *)iob1_right);
- if(iob2_left->ioa_Length!=0)
- {
- BeginIO((struct IORequest *)iob2_left);
- BeginIO((struct IORequest *)iob2_right);
- }
-
- /* If the sound sample was small enough to fit into the two buffers, */
- /* play them then finish up */
- if(length==0)
- {
- Wait((1<<iob1_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
- (1<<window->UserPort->mp_SigBit));
-
- if(iob2_left->ioa_Length!=0 && GetMsg(window->UserPort)==NULL)
- Wait((1<<iob2_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
- (1<<window->UserPort->mp_SigBit));
-
- done=TRUE;
- }
- /*Otherwise, play those samples then read more from disk*/
-
- /*Loop while there's stuff to read*/
- while(!done)
- {
- /*Wait for the first buffer to finish playing*/
- Wait((1<<iob1_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
- (1<<window->UserPort->mp_SigBit));
-
- toRead=MIN(length,bufSize);
-
- if(GetMsg(window->UserPort)!=NULL)
- {
- done=TRUE;
- break;
- }
- else
- if(toRead==0)
- {
- /*If there's no stuff left to read, wait 'till the second buffer*/
- /*finishes, then quit*/
- Wait((1<<iob1_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
- (1<<window->UserPort->mp_SigBit));
- done=TRUE;
- break;
- }
-
- LoadAudioBuffer(leftFile,iob1_left,toRead);
- LoadAudioBuffer(rightFile,iob1_right,toRead);
- length-=toRead;
- if(length==0 && loop)
- {
- length=sampleSize;
- Seek(leftFile,-sampleSize,OFFSET_CURRENT);
- Seek(rightFile,-sampleSize,OFFSET_CURRENT);
- }
-
- iob1_left->ioa_Length=iob1_right->ioa_Length=toRead;
-
- /*Play the first buffer*/
- BeginIO((struct IORequest *)iob1_left);
- BeginIO((struct IORequest *)iob1_right);
-
- /*Wait for the second buffer to finish*/
- Wait((1<<iob2_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
- (1<<window->UserPort->mp_SigBit));
-
- toRead=MIN(length,bufSize);
-
- if(GetMsg(window->UserPort)!=NULL)
- {
- done=TRUE;
- break;
- }
- else
- if(toRead==0)
- {
- /*If there's no stuff left to read, wait 'till the first buffer*/
- /*finishes, then quit*/
- Wait((1<<iob1_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
- (1<<window->UserPort->mp_SigBit));
- done=TRUE;
- break;
- }
-
- /*Reload it*/
- LoadAudioBuffer(leftFile,iob2_left,toRead);
- LoadAudioBuffer(rightFile,iob2_right,toRead);
- length-=toRead;
- if(length==0 && loop)
- {
- length=sampleSize;
- Seek(leftFile,-sampleSize,OFFSET_CURRENT);
- Seek(rightFile,-sampleSize,OFFSET_CURRENT);
- }
-
- iob2_left->ioa_Length=iob2_right->ioa_Length=toRead;
-
- /*Play it*/
- BeginIO((struct IORequest *)iob2_left);
- BeginIO((struct IORequest *)iob2_right);
- }
-
- /*Restore the buffer lengths, so that FreeAudio() channel, etc., knows*/
- /*how much memory to free*/
- iob1_left->ioa_Length=iob2_left->ioa_Length=bufSize;
- iob1_right->ioa_Length=iob2_right->ioa_Length=bufSize;
-
- FreeAudioChannel(iob1_left);
- DeleteDuplication(iob2_left);
- FreeAudioChannel(iob1_right);
- DeleteDuplication(iob2_right);
-
- if(rightFile != 4L)
- Close(rightFile);
-
- return;
- }
-
- /*Play a mono sample (or a single channel of a stereo sample) out of */
- /*both speakers simultaneously*/
- void playMonoTwice(BPTR file,channel audioChannel,struct Voice8Header *vhdr,
- ULONG length)
- {
- struct IOAudio *iob1_right,*iob2_right,*iob1_left,*iob2_left;
- ULONG toRead;
- ULONG sampleSize=length;
- BOOL done=FALSE;
-
- /*Read the entire sample into memory, if the user so specified*/
- if(readAll)
- {
- storeLeft(file,length,bufSize);
- file=0L;
- }
-
- /*Get the first audio channel*/
- iob1_left=GetAudioChannel(bufSize,leftAMap);
- if(iob1_left==NULL)
- {
- WriteMsg("Couldn't create the first stereo buffer\n");
- cleanup(150);
- }
-
- iob1_right=GetAudioChannel(bufSize,rightAMap);
- if(iob1_right==NULL)
- {
- WriteMsg("Couldn't create the second stereo buffer\n");
- cleanup(150);
- }
- FreeMem(iob1_right->ioa_Data,iob1_right->ioa_Length);
- iob1_right->ioa_Data=iob1_left->ioa_Data;
-
- /* If the user didn't specify a volume, get it from the VHDR */
- if(volume==0)
- volume=(vhdr->volume>>10);
-
- /* If the VHDR gave a volume of zero, use maximum volume*/
- if(volume==0)
- volume=64;
-
- /* Get the samples/sec rate (either the rate given by the user, or the*/
- /* rate found in the VHDR) */
- if(speed==0)
- speed=1000000000/(vhdr->samplesPerSec*279);
- else
- speed=1000000000/(speed*279);
-
- InitAudioChannel(iob1_left,volume,speed);
- InitAudioChannel(iob1_right,volume,speed);
-
- /*Get the 2nd audio channel*/
- iob2_left=DuplicateAudioChannel(iob1_left);
-
- if(iob2_left==NULL)
- {
- FreeAudioChannel(iob1_left);
- FreeAudioChannel(iob1_right);
- WriteMsg("Couldn't create the second buffer");
- cleanup(175);
- }
-
- iob2_right=DuplicateAudioChannel(iob1_right);
- if(iob2_right==NULL)
- {
- FreeAudioChannel(iob1_left);
- DeleteDuplication(iob2_left);
- FreeAudioChannel(iob1_right);
- WriteMsg("Couldn't create the second buffer");
- cleanup(175);
- }
- FreeMem(iob2_right->ioa_Data,iob2_right->ioa_Length);
- iob2_right->ioa_Data=iob2_left->ioa_Data;
-
- /* Load the first buffer*/
- toRead=MIN(length,bufSize);
- LoadAudioBuffer(file,iob1_left,toRead);
-
- length-=toRead;
- if(length==0 && loop)
- {
- length=sampleSize;
- Seek(file,-sampleSize,OFFSET_CURRENT);
- }
-
- iob1_right->ioa_Length=iob1_left->ioa_Length=toRead;
-
- /* Make sure there's enough data so that we have something to put in */
- /* the second buffer */
- if(length!=0)
- {
- toRead=MIN(length,bufSize);
- LoadAudioBuffer(file,iob2_left,toRead);
- length-=toRead;
- if(length==0 && loop)
- {
- length=sampleSize;
- Seek(file,-sampleSize,OFFSET_CURRENT);
- }
-
- iob2_right->ioa_Length=iob2_left->ioa_Length=toRead;
- }
- else
- /* It appears that the entire sound sample is small enough to */
- /* fit into the first buffer, so don't play the second */
- iob2_left->ioa_Length=iob2_right->ioa_Length=0;
-
- /*And queue up the play requests*/
- BeginIO((struct IORequest *)iob1_left);
- BeginIO((struct IORequest *)iob1_right);
- if(iob2_left->ioa_Length!=0)
- {
- BeginIO((struct IORequest *)iob2_left);
- BeginIO((struct IORequest *)iob2_right);
- }
-
- /* If the sound sample was small enough to fit into the two buffers, */
- /* play them then finish up */
- if(GetMsg(window->UserPort)!=NULL)
- done=TRUE;
- else
- if(length==0)
- {
- /* Bug!!! */
- Wait((1<<iob1_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
- (1<<window->UserPort->mp_SigBit));
-
- if(iob2_left->ioa_Length!=0 && GetMsg(window->UserPort)==NULL)
- Wait((1<<iob2_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
- (1<<window->UserPort->mp_SigBit));
-
- done=TRUE;
- }
- /*Otherwise, play those samples then read more from disk*/
-
- /*Loop while there's stuff to read*/
- while(!done)
- {
- /*Fill the first buffer*/
- Wait((1<<iob1_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
- (1<<window->UserPort->mp_SigBit));
-
- toRead=MIN(length,bufSize);
-
- if(GetMsg(window->UserPort)!=NULL)
- {
- done=TRUE;
- break;
- }
- else
- if(toRead==0)
- {
- /*If there's no stuff left to read, wait 'till the second buffer*/
- /*finishes, then quit*/
- Wait((1<<iob2_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
- (1<<window->UserPort->mp_SigBit));
- done=TRUE;
- break;
- }
-
- LoadAudioBuffer(file,iob1_left,toRead);
- length-=toRead;
- if(length==0 && loop)
- {
- length=sampleSize;
- Seek(file,-sampleSize,OFFSET_CURRENT);
- }
-
- iob1_right->ioa_Length=iob1_left->ioa_Length=toRead;
-
- /*Play the first buffer*/
- BeginIO((struct IORequest *)iob1_left);
- BeginIO((struct IORequest *)iob1_right);
-
- /*Wait for the second buffer to finish*/
- Wait((1<<iob2_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
- (1<<window->UserPort->mp_SigBit));
-
- toRead=MIN(length,bufSize);
-
- if(GetMsg(window->UserPort)!=NULL)
- {
- done=TRUE;
- break;
- }
- else
- if(toRead==0)
- {
- /*If there's no stuff left to read, wait 'till the first buffer*/
- /*finishes, then quit*/
- Wait((1<<iob1_left->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
- (1<<window->UserPort->mp_SigBit));
- done=TRUE;
- break;
- }
-
- /*Reload it*/
- LoadAudioBuffer(file,iob2_left,toRead);
- length-=toRead;
- if(length==0 && loop)
- {
- length=sampleSize;
- Seek(file,-sampleSize,OFFSET_CURRENT);
- }
-
- iob2_right->ioa_Length=iob2_left->ioa_Length=toRead;
-
- /*Play it*/
- BeginIO((struct IORequest *)iob2_left);
- BeginIO((struct IORequest *)iob2_right);
- }
-
- /*Restore the buffer lengths, so that FreeAudio() channel, etc., knows*/
- /*how much memory to free*/
- iob1_left->ioa_Length=iob2_left->ioa_Length=bufSize;
- iob1_right->ioa_Length=iob2_right->ioa_Length=bufSize;
-
- iob1_right->ioa_Data=NULL;
- iob2_right->ioa_Data=NULL;
-
- FreeAudioChannel(iob1_left);
- DeleteDuplication(iob2_left);
- FreeAudioChannel(iob1_right);
- DeleteDuplication(iob2_right);
-
- return;
- }
-
- /*End of Play.c*/
-